package com.trade.common.scheduler;

import com.trade.module.frontEndServer.FrontEndDBVo;
import lombok.extern.log4j.Log4j;

import java.util.Date;
import java.util.Timer;
import java.util.UUID;

/**
 * Description:前置机一次工作类，一次工作可以拆分为很多小的任务
 *
 * @JDK Version:1.8.0_40
 * Version: V1.0
 * Author: zfb
 * Date: 2016/3/24 10:51
 */
@Log4j
public class ClientWork<FrontEndVo> extends Timer {

    private String workId; //任务id

    private FrontEndVo taskParams; //前置机

    private int taskCount = 0; // 任务数

    private ClientWorkCallback clientWorkCallback;

    public ClientWork(FrontEndVo taskParams, ClientWorkCallback clientWorkCallback) {
        this.taskParams = taskParams;
        this.workId = UUID.randomUUID().toString();
        this.clientWorkCallback = clientWorkCallback;
        clientWorkCallback.workStarted(this.workId);
    }

    /**
     * 将任务加入执行列表,加入延时执行
     *
     * @param task  任务
     * @param delay 延迟时间毫秒，0为不延迟
     */
    public void schedule(ClientTask task, long delay) {
        scheduleTask(task);
        super.schedule(task, delay);
    }

    /**
     * 将任务加入的执行列表,按指定的日期时间执行
     *
     * @param task 任务
     * @param time 制定时间点
     */
    public void schedule(ClientTask task, Date time) {
        scheduleTask(task);
        super.schedule(task, time);
    }

    /**
     * 重复执行任务，按固定的任务间隔，但频率可能会有一些延时
     *
     * @param task   任务
     * @param delay  延迟时间毫秒，0为不延迟
     * @param period 重复执行时间间隔，时间间隔单位毫秒
     */
    public void schedule(ClientTask task, long delay, long period) {
        scheduleTask(task, period);
        super.schedule(task, delay, period);
    }

    /**
     * 以固定的时间作为起点，重复执行任务，按固定的任务间隔，但频率可能会有一些延时
     *
     * @param task      任务
     * @param firstTime 开始执行任务的时间
     * @param period    重复执行时间间隔，时间间隔单位毫秒
     */
    public void schedule(ClientTask task, Date firstTime, long period) {
        scheduleTask(task, period);
        super.schedule(task, firstTime, period);
    }

    /**
     * 重复执行任务，按固定的任务间隔，每次执行任务的频率一致
     *
     * @param task   任务
     * @param delay  延迟时间毫秒，0为不延迟
     * @param period 重复执行时间间隔，时间间隔单位毫秒
     */
    public void scheduleAtFixedRate(ClientTask task, long delay, long period) {
        scheduleTask(task, period);
        super.scheduleAtFixedRate(task, delay, period);
    }

    /**
     * 以固定的时间作为起点，重复执行任务，按固定的任务间隔，每次执行任务的频率一致
     *
     * @param task      任务
     * @param firstTime 开始执行任务的时间
     * @param period    重复执行时间间隔，时间间隔单位毫秒
     */
    public void scheduleAtFixedRate(ClientTask task, Date firstTime, long period) {
        scheduleTask(task, period);
        super.scheduleAtFixedRate(task, firstTime, period);
    }

    /**
     * 停止work
     */
    public void stopWork() {
        //取消所有的任务
        super.cancel();
        //清空被取消的所有任务
        super.purge();
    }

    private void scheduleTask(ClientTask task, long period) {
        task.setPeriod(period);
        scheduleTask(task);
    }

    private void scheduleTask(ClientTask task) {
        log.info("taskCount =" + taskCount);
        taskCount++;
        task.setClientTaskCallback(
                new ClientTaskCallback() {
                    @Override
                    public void taskStarted(TaskResultVo taskResultVo) {
                        clientWorkCallback.workStarted(workId);
                    }

                    @Override
                    public void taskFinished(TaskResultVo taskResultVo) {
                        taskResultVo.setWorkId(workId);
                        //如果是定时重复执行的任务则不需要结束任务
                        if (task.getPeriod() == null || task.getPeriod() <= 0) {
                            taskCount--;
                        }
                        if (taskCount <= 0) {
                            //所有的任务都已经执行完成，需要调用work回调，通知任务完成，并将数据传回给work
                            clientWorkCallback.workFinished(taskResultVo);
                            log.info("已完成任务表名称="+((FrontEndDBVo)taskResultVo.getFrontEndVo()).getTableName());
                            ClientWorkManager.getInstance().stopWorkByWorkId(workId);
                        }
                    }

                    @Override
                    public void taskPartialData(TaskResultVo taskResultVo) {
                        clientWorkCallback.workPartialData(taskResultVo);
                    }

                    @Override
                    public void dataQueryException(Exception e, FrontEndDBVo frontEndDBVoTemp) {
                        clientWorkCallback.dataQueryException(e,frontEndDBVoTemp);
                    }
                }
        );
    }




    public String getWorkId() {
        return workId;
    }

    public void setWorkId(String workId) {
        this.workId = workId;
    }

    public FrontEndVo getTaskParams() {
        return taskParams;
    }

    public void setTaskParams(FrontEndVo taskParams) {
        this.taskParams = taskParams;
    }
}
